import numpy as np
import matplotlib.pylab as plt

"""
数值微分
所谓数值微分就是用数值方法近似求解函数的导数的过程。
"""

# 求导
"""
求函数f在x值上的,间隔为1e-4的导数
f:函数
x:函数的参数
"""
def numerical_diff(f, x):
    h = 1e-4  # 0.0001
    return (f(x + h) - f(x - h)) / (2 * h)


def f1(x):
    return 0.01 * x ** 2 + 0.1 * x


# 求f1函数的导数
a = np.arange(0.0, 20.0, 0.1)
y = f1(a)
plt.xlabel(a)
plt.ylabel("f(x)")
plt.plot(a, y)
plt.show()

print(numerical_diff(f1, 5))
print(numerical_diff(f1, 10))

"""
由全部变量的偏导数汇总而成的向量称为梯度
"""
def numerical_gradient(f, x):
    h = 1e-4
    grad = np.zeros_like(x)  # 生成和x形状相同的数组
    for idx in range(x.size):
        tmp_val = x[idx]

        x[idx] = tmp_val + h
        fxh1 = f(x)

        x[idx] = tmp_val - h
        fxh2 = f(x)

        grad[idx] = (fxh1 - fxh2) / (2 * h)
        x[idx] = tmp_val
    return grad
